package com.lys.lock;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class LockUtil implements AsyncCallback.StringCallback, Watcher, AsyncCallback.ChildrenCallback, AsyncCallback.StatCallback {
    private ZooKeeper zooKeeper;
    private CountDownLatch countDownLatch;
    private String nodePath;
    private String threadName;

    public void setZooKeeper(ZooKeeper zooKeeper) {
        this.zooKeeper = zooKeeper;
    }

    /**
     * 获取锁
     */
    public void tryLock(){
        threadName = Thread.currentThread().getName();
        countDownLatch = new CountDownLatch(1);
        zooKeeper.create("/lock",threadName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,this,"abc");
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 释放锁
     */
    public void reLock(){
        try {
            zooKeeper.delete("/"+nodePath,-1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }

    // create call back
    @Override
    public void processResult(int rc, String path, Object ctx, String name) {
        if (name!=null){
            nodePath = name.substring(1);
            System.out.println(threadName+"create node:"+name);
            zooKeeper.getChildren("/",false, this, "aaa");
        }
    }

    // Watcher
    @Override
    public void process(WatchedEvent event) {
        switch (event.getType()) {
            case None:
                break;
            case NodeCreated:
                break;
            case NodeDeleted:
                System.out.println("节点被删除");
                zooKeeper.getChildren("/",false, this, "aaa");
                break;
            case NodeDataChanged:
                break;
            case NodeChildrenChanged:
                break;
//            case DataWatchRemoved:
//                break;
//            case ChildWatchRemoved:
//                break;
//            case PersistentWatchRemoved:
//                break;
        }
    }

    // getChildren call back
    @Override
    public void processResult(int rc, String path, Object ctx, List<String> children) {
        if (children==null) {
            return;
        }
        String node = nodePath;
        Collections.sort(children);
        if (children.get(0).equals(node)){
            // 自己就是最小的，所以成功拿到锁
            System.out.println(threadName+"拿到锁1");
            countDownLatch.countDown();
        }else {
            int index = children.indexOf(node) - 1;
            zooKeeper.exists("/"+children.get(index),this,this,"bbb");
        }
    }

    // exists call back
    @Override
    public void processResult(int rc, String path, Object ctx, Stat stat) {
        if (stat==null) {
            zooKeeper.getChildren("/",false, this, "aaa");
        }
    }
}
